package model

import (
	"common/helper"
	"database/sql"
	"errors"
	"fmt"
	g "github.com/doug-martin/goqu/v9"
	"github.com/doug-martin/goqu/v9/exp"
	"time"
)

type lastWinRecord struct {
	Uid        string `json:"uid"`
	GameName   string `json:"game_name" db:"game_name"`
	GameId     string `json:"game_id" db:"game_id"`
	PlatformId string `json:"platform_id" db:"platform_id"`
	Amount     string `json:"amount"`
}
type lastWinRecordData struct {
	T int             `json:"t"`
	D []lastWinRecord `json:"d"`
}

type trade struct {
	Flag      int     `json:"flag" cbor:"flag"`             //前端传入 271 存款 272 取款
	ID        string  `json:"id" cbor:"id"`                 //id
	BillNo    string  `json:"bill_no" cbor:"bill_no"`       //流水号
	Amount    string  `json:"amount" cbor:"amount"`         //金额
	CreatedAt string  `json:"created_at" cbor:"created_at"` //创建时间
	State     int     `json:"state" cbor:"state"`           //0:失败1:成功 2:处理中 3:失败
	Fname     string  `json:"fname" cbor:"fname"`           //支付方式
	Discount  string  `json:"discount" cbor:"discount"`     //优惠
	UsdtRate  float64 `json:"usdt_rate" cbor:"usdt_rate"`   //汇率
	UsdtCount float64 `json:"usdt_count" cbor:"usdt_count"` //usdt个数
}

type TradeData struct {
	T int64   `json:"t"`
	D []trade `json:"d"`
	S uint    `json:"s"`
}

type gameRecordDetail struct {
	RowId     string  `db:"row_id" json:"row_id"`
	GameName  string  `db:"game_name" json:"game_name"`
	BetTime   int64   `db:"bet_time" json:"bet_time"`
	BetAmount float64 `db:"bet_amount" json:"bet_amount"`
	NetAmount float64 `db:"net_amount" json:"net_amount"`
}

type gameRecordData struct {
	T int64              `json:"t"`
	D []gameRecordDetail `json:"d"`
	S uint               `json:"s"`
}

func LastWinRecord() (lastWinRecordData, error) {

	data := lastWinRecordData{}
	var list []lastWinRecord
	t := dialect.From("tbl_game_lists")
	query, _, _ := t.Select(g.C("en_name").As("game_name"), g.C("platform_id"), g.C("game_id")).Limit(100).ToSQL()
	err := meta.SlaveDB.Select(&list, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
	}
	selectedElements := make([]lastWinRecord, 100)
	for i := 0; i < 100; i++ {
		index := meta.Rand.Intn(len(list))
		lr := list[index]
		lr.Uid = "**********" + rand(4)
		lr.Amount = fmt.Sprintf("%d%s", meta.Rand.Intn(9), rand(meta.Rand.Intn(7)))
		selectedElements[i] = lr
	}
	data.T = len(selectedElements)
	data.D = selectedElements

	return data, nil
}

// 交易记录
func RecordTrade(uid string, flag int, page, pageSize uint) (TradeData, error) {

	data := TradeData{}

	ex := g.Ex{"uid": uid}
	switch flag {
	case RecordTradeWithdraw: // 取款
		return recordTradeWithdraw(flag, page, pageSize, ex, "", 0)

	case RecordTradeDeposit: // 存款
		return recordTradeDeposit(flag, page, pageSize, ex, "", 0)
	}

	return data, errors.New(helper.GetDataFailed)
}

// 取款
func recordTradeWithdraw(flag int, page, pageSize uint,
	ex g.Ex, sortField string, isAsc int) (TradeData, error) {

	data := TradeData{}
	var list []tblWithdraw
	//ex["prefix"] = meta.Prefix

	if page == 1 {
		query, _, _ := dialect.From("tbl_withdraw").Select(g.COUNT("id")).Where(ex).Limit(1).ToSQL()
		err := meta.SlaveDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		if data.T == 0 {
			return data, nil
		}
	}

	orderBy := "created_at"
	if sortField != "" {
		orderBy = sortField
	}

	order := g.C(orderBy).Desc()
	if isAsc == 1 {
		order = g.C(orderBy).Asc()
	}

	offset := (page - 1) * pageSize
	query, _, _ := dialect.From("tbl_withdraw").Select(colsWithdraw...).Where(ex).Order(order).Offset(offset).Limit(pageSize).ToSQL()
	err := meta.SlaveDB.Select(&list, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
	}

	for _, v := range list {
		item := trade{
			Flag:      flag,
			ID:        v.ID,
			BillNo:    v.ID,
			Amount:    fmt.Sprintf("%.4f", v.Amount),
			CreatedAt: fmt.Sprintf("%d", v.CreatedAt),
		}
		switch v.State {
		case WithdrawSuccess:
			item.State = 1
		case WithdrawFailed:
			item.State = 3
		default:
			item.State = 2
		}

		data.D = append(data.D, item)
	}

	return data, nil
}

// 存款
func recordTradeDeposit(flag int, page, pageSize uint,
	ex g.Ex, sortField string, isAsc int) (TradeData, error) {

	data := TradeData{}
	var list []TblDeposit
	if page == 1 {
		query, _, _ := dialect.From("tbl_deposit").Select(g.COUNT("id")).Where(ex).Limit(1).ToSQL()
		err := meta.SlaveDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		if data.T == 0 {
			return data, nil
		}
	}

	orderBy := "created_at"
	if sortField != "" {
		orderBy = sortField
	}

	order := g.C(orderBy).Desc()
	if isAsc == 1 {
		order = g.C(orderBy).Asc()
	}

	offset := (page - 1) * pageSize
	query, _, _ := dialect.From("tbl_deposit").Select(colsDeposit...).Where(ex).Order(order).Offset(offset).Limit(pageSize).ToSQL()
	err := meta.SlaveDB.Select(&list, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
	}

	for _, v := range list {
		item := trade{
			ID:        v.Id,
			Flag:      flag,
			BillNo:    v.Id,
			Amount:    fmt.Sprintf("%s", v.Amount),
			CreatedAt: fmt.Sprintf("%d", v.CreatedAt),
			Fname:     v.Fname,
			Discount:  fmt.Sprintf(`%f`, v.Discount),
		}
		switch v.State {
		case DepositSuccess:
			item.State = 1
		//case DepositCancelled:
		//	item.State = 3
		default:
			item.State = 2
		}
		data.D = append(data.D, item)
	}

	return data, nil
}

// 存款
func GameRecord(uid string, ty, flag, gt int, page, pageSize uint) (gameRecordData, error) {

	data := gameRecordData{}
	var startAt int64
	endAt := helper.DayTET(0, loc).UnixMilli()

	switch flag {
	case 1:
		startAt = helper.DayTST(0, loc).UnixMilli()
	case 7:
		sevenDaysAgo := time.Now().AddDate(0, 0, -7)
		sevenDaysAgoMidnight := time.Date(sevenDaysAgo.Year(), sevenDaysAgo.Month(), sevenDaysAgo.Day(), 0, 0, 0, 0, time.UTC)
		// 获取七天前0点0时0分的时间戳
		startAt = sevenDaysAgoMidnight.UnixMilli()
	case 60:
		sevenDaysAgo := time.Now().AddDate(0, 0, -60)
		sevenDaysAgoMidnight := time.Date(sevenDaysAgo.Year(), sevenDaysAgo.Month(), sevenDaysAgo.Day(), 0, 0, 0, 0, time.UTC)
		startAt = sevenDaysAgoMidnight.UnixMilli()
	}
	ex := g.Ex{
		"uid":      uid,
		"bet_time": g.Op{"between": exp.NewRangeVal(startAt, endAt)},
	}
	if gt == 1 {
		ex["net_amount"] = g.Op{"gt": 0}
	}
	if ty > 0 {
		ex["game_type"] = fmt.Sprintf(`%d`, ty)
	}
	if page == 1 {
		query, _, _ := dialect.From("tbl_game_record").Select(g.COUNT("row_id")).Where(ex).Limit(1).ToSQL()
		err := meta.SlaveDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		if data.T == 0 {
			return data, nil
		}
	}

	orderBy := "bet_time"
	order := g.C(orderBy).Desc()

	offset := (page - 1) * pageSize
	query, _, _ := dialect.From("tbl_game_record").Select(g.C("row_id"), g.C("game_name"), g.C("bet_time"), g.C("bet_amount"), g.C("net_amount")).Where(ex).Order(order).Offset(offset).Limit(pageSize).ToSQL()
	err := meta.SlaveDB.Select(&data.D, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
	}

	return data, nil
}

type bonusRecord struct {
	Id        string `json:"id" db:"id"`
	CreatedAt int64  `json:"created_at" db:"created_at"`
	Ty        string `json:"ty" db:"ty"`
	Amount    string `json:"amount" db:"amount"`
	Remark    string `json:"remark" db:"remark"`
}

type bonusRecordData struct {
	T int           `json:"t"`
	D []bonusRecord `json:"d"`
	S int           `json:"s"`
}

type tblPromoInviteRecord struct {
	Id             string  `db:"id" json:"id"`
	Uid            string  `db:"uid" json:"uid"`
	Username       string  `db:"username" json:"username"`
	Lvl            int     `db:"lvl" json:"lvl"`                           //123 一级二级三级
	ChildUid       string  `db:"child_uid" json:"child_uid"`               //下级的uid
	ChildUsername  string  `db:"child_username" json:"child_username"`     //下级的账号
	FirstDepositAt int     `db:"first_deposit_at" json:"first_deposit_at"` //首存时间
	DepositAmount  float64 `db:"deposit_amount" json:"deposit_amount"`     //存款金额
	BonusAmount    float64 `db:"bonus_amount" json:"bonus_amount"`         //奖金
	CreatedAt      uint32  `db:"created_at" json:"created_at"`             //注册时间
	State          int     `db:"state" json:"state"`                       //状态1注册未充值2充值未结算3已结算4过期作废
}

type inviteRecordData struct {
	T int                    `cbor:"t" json:"t"`
	D []tblPromoInviteRecord `cbor:"d" json:"d"`
}

func InviteRecord(uid string, startTime, endTime string, flag, lvl string, page, pageSize uint) (inviteRecordData, error) {

	data := inviteRecordData{}
	ex := g.Ex{}
	if startTime != "" && endTime != "" {

		startAt, err := helper.TimeToLoc(startTime, loc)
		if err != nil {
			return data, errors.New(helper.DateTimeErr)
		}

		endAt, err := helper.TimeToLoc(endTime, loc)
		if err != nil {
			return data, errors.New(helper.DateTimeErr)
		}

		if startAt >= endAt {
			return data, errors.New(helper.QueryTimeRangeErr)
		}

		ex["created_at"] = g.Op{"between": exp.NewRangeVal(startAt, endAt)}
	}

	if flag == "1" {
		ex["deposit_amount"] = g.Op{"gt": 0}
	}
	if flag == "2" {
		ex["deposit_amount"] = 0
	}
	if lvl == "1" {
		ex["lvl"] = lvl
		ex["uid"] = uid

		if page == 1 {
			query, _, _ := dialect.From("tbl_promo_invite_record").Select(g.COUNT("id")).Where(ex).Limit(1).ToSQL()
			err := meta.SlaveDB.Get(&data.T, query)
			if err != nil {
				return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
			}
			if data.T == 0 {
				return data, nil
			}
		}

		orderBy := "created_at"
		order := g.C(orderBy).Desc()

		offset := (page - 1) * pageSize
		query, _, _ := dialect.From("tbl_promo_invite_record").Select(colsInviteRecord...).Where(ex).Order(order).Offset(offset).Limit(pageSize).ToSQL()
		err := meta.SlaveDB.Select(&data.D, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		//for i, v := range data.D {
		//	child, _ := myUserHelp.GetMemberBaseInfoByUid(v.ChildUid)
		//	data.D[i].BonusAmount = child.Score
		//}
	} else if lvl == "2" || lvl == "3" {
		ex["child_uid"] = g.Op{"in": g.L(fmt.Sprintf(`select descendant from tbl_members_tree where ancestor = %s and lvl =%s`, uid, lvl))}

		if page == 1 {
			query, _, _ := dialect.From("tbl_promo_invite_record").Select(g.COUNT("id")).Where(ex).Limit(1).ToSQL()
			err := meta.SlaveDB.Get(&data.T, query)
			if err != nil {
				return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
			}
			if data.T == 0 {
				return data, nil
			}
		}
		orderBy := "created_at"
		order := g.C(orderBy).Desc()

		offset := (page - 1) * pageSize
		query, _, _ := dialect.From("tbl_promo_invite_record").Select(colsInviteRecord...).Where(ex).Order(order).Offset(offset).Limit(pageSize).ToSQL()
		err := meta.SlaveDB.Select(&data.D, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), helper.DBErr)
		}
		//for i, v := range data.D {
		//	child, _ := myUserHelp.GetMemberBaseInfoByUid(v.ChildUid)
		//	data.D[i].BonusAmount = child.Score
		//}
	}

	return data, nil
}

type PromoInspection struct {
	ID              string  `json:"ID" db:"ID"`
	AddTime         string  `json:"AddTime" db:"AddTime"`
	ChangeMoney     float64 `json:"ChangeMoney" db:"ChangeMoney"`         //金额变化
	NeedWageRequire float64 `json:"NeedWageRequire" db:"NeedWageRequire"` //需要的打码量
	CurWageRequire  float64 `json:"CurWageRequire" db:"CurWageRequire"`   //当前打码量
	Status          int     `json:"Status" db:"Status"`                   // 状态  0 非完成 1=已完成
	ChangeType      int     `json:"ChangeType" db:"ChangeType"`
}

func PromoRecordList(uid string) ([]PromoInspection, error) {
	var data []PromoInspection
	SqlSelect := fmt.Sprintf("Select ID,CONVERT(AddTime,CHAR) as AddTime,ChangeMoney,NeedWageRequire,CurWageRequire,Status,ChangeType from tbl_member_wage_require "+
		"where uid=%s order by ID desc", uid)
	GetSlaveDBInstance().Select(&data, SqlSelect)
	return data, nil
}
